//
// GPSMapEdit
// (c) Konstantin Galichsky (kg@geopainting.com), 2002-2006
//
// GDI+ access stuff.
//

# include "StdAfx.h"
# include "MiniGDI+.h"
# include "Log.h"
# include "Globals.h"

pfGdiplusStartup_t         g_pfGdiplusStartup;
pfGdiplusShutdown_t        g_pfGdiplusShutdown;
pfGdipCreateFromHDC_t      g_pfGdipCreateFromHDC;
pfGdipDeleteGraphics_t     g_pfGdipDeleteGraphics;
pfGdipLoadImageFromFile_t  g_pfGdipLoadImageFromFile;
pfGdipDisposeImage_t       g_pfGdipDisposeImage;
pfGdipGetImageWidth_t      g_pfGdipGetImageWidth;
pfGdipGetImageHeight_t     g_pfGdipGetImageHeight;
pfGdipDrawImageRectRectI_t g_pfGdipDrawImageRectRectI;

pfGdipGetImageGraphicsContext_t g_pfGdipGetImageGraphicsContext;

pfGdipGetImageDecodersSize_t g_pfGdipGetImageDecodersSize;
pfGdipGetImageDecoders_t     g_pfGdipGetImageDecoders;

static HMODULE g_hGDIPlusDll;

struct _VS_VERSIONINFO {
	WORD  wLength; 
	WORD  wValueLength; 
	WORD  wType; 
	WCHAR szKey [15 + 1]; // "VS_VERSION_INFO"
//		WORD  Padding1 [1];
	VS_FIXEDFILEINFO Value;
};

bool InitGdiPlus () {
	if (g_hGDIPlusDll)
		return true;

	ReportText ("Initializing GDI+ API...");

	//
	// First try to load from system directory.
	//

	// NOTE: under Windows XP, it is required to use the system-supplied gdiplus.dll.
	char strSystem [MAX_PATH];
	::GetSystemDirectory (strSystem, MAX_PATH);
	::strcat (strSystem, "\\gdiplus.dll");
	g_hGDIPlusDll = ::LoadLibraryEx (strSystem, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
	if (! g_hGDIPlusDll) {
		// Second, try local one.
		g_hGDIPlusDll = ::LoadLibrary ("gdiplus.dll");
		if (g_hGDIPlusDll == NULL) {
			// TODO: Extract from resource?
			ReportWarning ("Failed to load GdiPlus.dll.");
			return false;
		}
	}
/*
	//
	// Check version of GDI+.
	//

	const HRSRC hRsrc = ::FindResource (g_hGDIPlusDll, MAKEINTRESOURCE (VS_VERSION_INFO), RT_VERSION);
	const HGLOBAL hGlobal = ::LoadResource (g_hGDIPlusDll, hRsrc);
	void * const pVerData = ::LockResource (hGlobal);
	const _VS_VERSIONINFO * const pVerHdr = reinterpret_cast<const _VS_VERSIONINFO *> (pVerData);
	if (pVerHdr->Value.dwSignature == 0xFEEF04BD) {
		if (
			pVerHdr->Value.dwFileVersionMS < 0x00050001 || // 5.1.3102.1360 (xpsp2.040109-1800)
			(
				pVerHdr->Value.dwFileVersionMS == 0x00050001 &&
				pVerHdr->Value.dwFileVersionLS <  0x0c1e0550
			)
		)
			WarningMsgBox (
				_T ("Obsolete version of GDI+ library (gdiplus.dll) is used.\n")
				_T ("This one has serious security hole which is now fixed by Microsoft.\n")
				_T ("Please visit http://www.geopainting.com/en/gdiplus.html for details.")
			);
	}*/

	//
	// Find entry points.
	//

	g_pfGdiplusStartup              = reinterpret_cast<pfGdiplusStartup_t>              (::GetProcAddress (g_hGDIPlusDll, "GdiplusStartup"));
	g_pfGdiplusShutdown             = reinterpret_cast<pfGdiplusShutdown_t>             (::GetProcAddress (g_hGDIPlusDll, "GdiplusShutdown"));
	g_pfGdipCreateFromHDC           = reinterpret_cast<pfGdipCreateFromHDC_t>           (::GetProcAddress (g_hGDIPlusDll, "GdipCreateFromHDC"));
	g_pfGdipDeleteGraphics          = reinterpret_cast<pfGdipDeleteGraphics_t>          (::GetProcAddress (g_hGDIPlusDll, "GdipDeleteGraphics"));
	g_pfGdipLoadImageFromFile       = reinterpret_cast<pfGdipLoadImageFromFile_t>       (::GetProcAddress (g_hGDIPlusDll, "GdipLoadImageFromFile"));
	g_pfGdipDisposeImage            = reinterpret_cast<pfGdipDisposeImage_t>            (::GetProcAddress (g_hGDIPlusDll, "GdipDisposeImage"));
	g_pfGdipGetImageWidth           = reinterpret_cast<pfGdipGetImageWidth_t>           (::GetProcAddress (g_hGDIPlusDll, "GdipGetImageWidth"));
	g_pfGdipGetImageHeight          = reinterpret_cast<pfGdipGetImageHeight_t>          (::GetProcAddress (g_hGDIPlusDll, "GdipGetImageHeight"));
	g_pfGdipDrawImageRectRectI      = reinterpret_cast<pfGdipDrawImageRectRectI_t>      (::GetProcAddress (g_hGDIPlusDll, "GdipDrawImageRectRectI"));
	g_pfGdipGetImageDecodersSize    = reinterpret_cast<pfGdipGetImageDecodersSize_t>    (::GetProcAddress (g_hGDIPlusDll, "GdipGetImageDecodersSize"));
	g_pfGdipGetImageDecoders        = reinterpret_cast<pfGdipGetImageDecoders_t>        (::GetProcAddress (g_hGDIPlusDll, "GdipGetImageDecoders"));
	g_pfGdipGetImageGraphicsContext = reinterpret_cast<pfGdipGetImageGraphicsContext_t> (::GetProcAddress (g_hGDIPlusDll, "GdipGetImageGraphicsContext"));
	if (
		! g_pfGdiplusStartup ||
		! g_pfGdiplusShutdown ||
		! g_pfGdipCreateFromHDC ||
		! g_pfGdipDeleteGraphics ||
		! g_pfGdipLoadImageFromFile ||
		! g_pfGdipDisposeImage ||
		! g_pfGdipGetImageWidth ||
		! g_pfGdipGetImageHeight ||
		! g_pfGdipDrawImageRectRectI ||
		! g_pfGdipGetImageDecodersSize ||
		! g_pfGdipGetImageDecoders ||
		! g_pfGdipGetImageGraphicsContext
	) {
		ReportWarning ("Cannot find entry points in gdiplus.dll.");
		return false;
	}

	//
	// Initialize GDI+.
	//

	ULONG_PTR token;
	GdiplusStartupInput si;
	Status s = g_pfGdiplusStartup (& token, & si, NULL);
	if (s != 0) {
		ReportWarning ("Failed to initialize GDI+. Error code: %d.", s);
		g_hGDIPlusDll = NULL;
		return false;
	}

	return true;
}
